#pragma once
#include "DXAMLCommon.h"

#include "XamlNode.h"
#include "XamlParserContext.h"
#include "XamlScanner.h"
#include "XamlNodeStreamValidator.h"
#include "IPullParserNodeCallback.h"
#include "XamlParserState.h"

class XamlPullParser :
	public IPullParserNodeCallback
{
public: 
	XamlPullParser(const xshared_ptr<XamlParserContext> & inContext, const xshared_ptr<XamlScanner> & inScanner);
	HRESULT Parse(XamlNode & outNode);
	enum XamlParserState::ParseState CurrentState();
	enum XamlParserState::ParseState PreviousState();
	class PrefixNamespacePair
	{

	public: 
		PrefixNamespacePair(class xshared_ptr<CXString> inPrefix, class xshared_ptr<XamlNamespace> inNamespace, const XamlLineInfo & inLineInfo);
		xshared_ptr<CXString> m_Prefix;
		xshared_ptr<XamlNamespace> m_Namespace;
		XamlLineInfo m_LineInfo;
	};
private: 
	virtual HRESULT AcceptNode(const XamlNode & node);
	void SetLineInfoOnWorkingNode(const XamlLineInfo & inLineInfo);
	void SetLineInfoOnWorkingNode();
	HRESULT EnqueueWorkingNode(const XamlLineInfo & inLineInfo);
	HRESULT EnqueueWorkingNode();
	HRESULT InternalEnqueueNode(const XamlNode & node);
	HRESULT Logic_PrefixDefinition();
	HRESULT Logic_StartElement();
	HRESULT Logic_StartEmptyElement();
	HRESULT Logic_StartPropertyElement();
	HRESULT Logic_EndObject();
	HRESULT Logic_EndMember();
	HRESULT Logic_EndElement();
	HRESULT Logic_Attribute();
	HRESULT Logic_Directive();
	HRESULT Logic_TextContent();
	HRESULT Logic_EndOfAttributes();
	HRESULT Logic_EndOfStream();
	HRESULT Logic_AttributeOrDirective(XBOOL bIsDirective);
	HRESULT Logic_StartInitProperty(const xshared_ptr<XamlType> & inType);
	HRESULT Logic_StartItemsProperty(const xshared_ptr<XamlType> & inCollectionType);
	HRESULT Logic_AttributeValueNode(const xshared_ptr<XamlText> & inXamlText);
	HRESULT Logic_TextValueNode(const xshared_ptr<XamlText> & inXamlText);
	HRESULT Logic_StartObject(const xshared_ptr<XamlType> & inXamlType, const enum XamlParserFrame::ElementKind & inElementKind);
	HRESULT Logic_StartObject(const enum XamlParserFrame::ElementKind & inElementKind);
	HRESULT Logic_StartMember(const xshared_ptr<XamlProperty> & inXamlProperty);
	HRESULT Logic_StartContentProperty(const xshared_ptr<XamlProperty> & inContentProperty);
	HRESULT Logic_StartGetObjectFromMember(const xshared_ptr<XamlType> & inPropertyType);
	HRESULT Logic_CheckForStartGetCollectionFromMember();
	HRESULT Logic_EndCollectionFromMember();
	HRESULT Logic_EndItemsProperty();
	HRESULT Logic_EndContentProperty();
	HRESULT Logic_ApplyFinalTextTrimming(const xshared_ptr<XamlText> & spText, xshared_ptr<CXString> & spTrimmed);
	HRESULT Logic_IsDiscardableWhitespace(const xshared_ptr<XamlText> & spText, XBOOL & bIsDiscardable);
	HRESULT CanAcceptString(const xshared_ptr<XamlProperty> & spXamlProperty, XBOOL & bCanAcceptString);
	HRESULT EmitImplicitPreambleNodesIfRequired(const xshared_ptr<XamlType> & inXamlType);
	HRESULT EmitPendingNamespaceNodes();
	HRESULT IsInElementContent(XBOOL & bIsInElementContent);
	HRESULT PopImplicitNodesIfRequired();
	xshared_ptr<XamlParserContext> m_ParserContext;
	xshared_ptr<XamlScanner> m_Scanner;
	xshared_ptr<XamlText> m_PendingXamlText;
	xqueue<XamlNode> m_NodeQueue;
	xvector<XamlPullParser::PrefixNamespacePair> m_PendingNamespaces;
	XamlNodeStreamValidator m_Validator;
	XamlParserState m_ParserState;
	XamlNode m_WorkingNode;
};




